package pers.xiaojun.boot.module.system.service.dept;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import pers.xiaojun.boot.common.enums.CommonStatusEnum;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.module.system.controller.dept.vo.dept.DeptQueryReqVO;
import pers.xiaojun.boot.module.system.controller.dept.vo.dept.DeptSaveReqVO;
import pers.xiaojun.boot.module.system.dao.entity.dept.DeptDO;
import pers.xiaojun.boot.module.system.dao.mapper.dept.DeptMapper;

import java.util.List;

import static pers.xiaojun.boot.module.system.constants.BusinessCodeConstants.*;

/**
 * 部门服务实现类
 *
 * @author xiaojun
 * @since 2025-11-01
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, DeptDO> implements DeptService {

    private static final Long DEPT_ROOT_ID = 0L;

    @Override
    public DeptDO saveDept(DeptSaveReqVO saveVO) {
        // 校验基础信息
        validateDeptBasicInfo(saveVO.getName(), saveVO.getParentId(), null);

        DeptDO dept = BeanUtil.toBean(saveVO, DeptDO.class);
        this.baseMapper.insert(dept);

        return dept;
    }

    @Override
    public DeptDO updateDept(DeptSaveReqVO updateVO) {
        // 校验部门是否存在
        validateDeptExists(updateVO.getId());

        // 校验基础信息
        validateDeptBasicInfo(updateVO.getName(), updateVO.getParentId(), updateVO.getId());

        DeptDO dept = BeanUtil.toBean(updateVO, DeptDO.class);
        this.baseMapper.updateById(dept);

        return dept;
    }

    @Override
    public void removeDeptById(Long deptId) {
        // 校验部门是否存在
        validateDeptExists(deptId);
        // 校验部门不能存在下级部门
        validateDeptChildrenNotAllowed(deptId);

        this.baseMapper.deleteById(deptId);
    }

    @Override
    public void removeDeptByIds(List<Long> deptIds) {
        for (Long deptId : deptIds) {
            validateDeptExists(deptId);
            validateDeptChildrenNotAllowed(deptId);
        }

        this.baseMapper.deleteByIds(deptIds);
    }

    @Override
    public DeptDO getDeptById(Long deptId) {
        return validateDeptExists(deptId);
    }

    @Override
    public List<DeptDO> listDepts(DeptQueryReqVO queryVO) {
        return this.baseMapper.selectList(new LambdaQueryWrapper<DeptDO>()
                .like(queryVO.getName() != null, DeptDO::getName, queryVO.getName())
                .eq(queryVO.getStatus() != null, DeptDO::getStatus, queryVO.getStatus())
        );
    }

    @Override
    public DeptDO validateDeptIsEnabled(Long deptId) {
        DeptDO dept = validateDeptExists(deptId);

        if (CommonStatusEnum.isDisable(dept.getStatus())) {
            throw new BusinessException(DEPT_DISABLE);
        }
        return dept;
    }

    /**
     * 校验部门基础信息
     *
     * @param name     部门名称
     * @param parentId 上级部门Id
     */
    private void validateDeptBasicInfo(String name, Long parentId, Long deptId) {
        // 部门名称需要不存在
        DeptDO dept = this.baseMapper.selectByNameAndParentId(name, parentId);
        if (dept != null && !dept.getId().equals(deptId)) {
            throw new BusinessException(DEPT_NAME_EXISTS);
        }

        // 非顶级部门才要判断
        if (!DEPT_ROOT_ID.equals(parentId)) {
            // 上级部门不能为自己
            if (parentId.equals(deptId)) {
                throw new BusinessException(DEPT_PARENT_NOT_MYSELF);
            }
            // 上级部门需要存在
            dept = this.baseMapper.selectById(parentId);
            if (dept == null) {
                throw new BusinessException(DEPT_PARENT_NOT_EXISTS);
            }
        }

    }

    /**
     * 校验部门是否存在
     *
     * @param deptId 部门Id
     * @return 部门
     */
    private DeptDO validateDeptExists(Long deptId) {
        DeptDO dept = this.baseMapper.selectById(deptId);
        if (dept == null) {
            throw new BusinessException(DEPT_NOT_EXISTS);
        }
        return dept;
    }

    /**
     * 校验部门不允许有下级部门
     *
     * @param deptId 部门Id
     */
    private void validateDeptChildrenNotAllowed(Long deptId) {
        if (CollUtil.isNotEmpty(this.baseMapper.selectByParentId(deptId))) {
            throw new BusinessException(DEPT_HAS_CHILDREN);
        }
    }

}
